home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-05-01 | 55.0 KB | 1,961 lines | [TEXT/MPS ] |
- // UList.cp
- // Copyright © 1986-1991 by Apple Computer, Inc. All rights reserved.
-
- #ifndef __ULIST__
- #include <UList.h>
- #endif
-
- #ifndef __STDIO__
- #include <StdIo.h>
- #endif
-
- #ifndef __PACKAGES__
- #include <Packages.h>
- #endif
-
- #ifndef __UFAILURE__
- #include <UFailure.h>
- #endif
-
- #ifndef __UMACAPPUTILITIES__
- #include <UMacAppUtilities.h>
- #endif
-
- #ifndef __UITERATOR__
- #include <UIterator.h>
- #endif
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::Initialize(void) // override
- {
- inherited::Initialize();
-
- fIteratorPtr = NULL;
-
- fAllocatedSize = kEmptyIndex;
- fAllocationIncrement = kAllocationIncrement;// !!! an enhancement would be to support
- // no-growth lists. i.e. fAllocationIncrement
- // of kEmptyIndex. the list would just stay
- // at the size it was allocated and wouldn't
- // shrink and signal failure if an operation
- // needed to grow it
- //!!!fClassSize = this->GetClassSize();
- fElementSize = 1;
- fElementSizeShift = 0; //!!!
- fFreeRequested = FALSE; // no comment can do this justice
- fSize = kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::IDynamicArray(ArrayIndex initialSize,
- short elementSize)
- {
- this->IObject();
-
- fClassSize = this->GetClassSize(); // Store the class size for use in computeAddress
-
- if (qDebug && (initialSize < kEmptyIndex))
- {
- ProgramBreak("initialSize must be non-negative!");
- initialSize = kEmptyIndex; //??? Ask programmer
- }
-
- if (qDebug && (elementSize <= 0))
- {
- ProgramBreak("In TDynamicArray.IDynamicArray: preposterous element size. (zero or negative)");
- Failure(minErr, 0);
- }
-
- fSize = kEmptyIndex;
-
- fElementSize = elementSize;
- fAllocatedSize = kEmptyIndex;
-
- // calculate the elementsizeshift that represents the nearest power of 2
- fElementSizeShift = 0;
- while (((elementSize - 1) >> fElementSizeShift) > 0)
- ++fElementSizeShift;
-
- this->SetArraySize(initialSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::DeleteElementsAt(ArrayIndex index,
- ArrayIndex count)
- {
- const SignedByte initVal = 0xF1;
-
- Ptr indexPtr, nextElementPtr, lastElementPtr;
- ArrayIndex countBytes;
-
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TDynamicArray.DeleteElementAt");
- }
-
- countBytes = count << fElementSizeShift;
-
- indexPtr = this->ComputeAddress(index);
- nextElementPtr = this->ComputeAddress(index + count);
- lastElementPtr = this->ComputeAddress(fSize + 1);
-
- if (nextElementPtr < lastElementPtr) // deleted from middle? Compress the array
- BlockMove(nextElementPtr, indexPtr, (long)lastElementPtr - (long)nextElementPtr);
-
- if (qDebug)
- BlockSet((Ptr)((long)lastElementPtr - countBytes), countBytes, initVal);
-
- this->SetArraySize(fSize - count); // take up slack if necessary. Should never
- // Fail when shrinking array.
- fSize -= count;
-
- if (fIteratorPtr) // Keep all iterations apprised
- fIteratorPtr->DeleteElementAt(index, count);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::GetElementsAt(ArrayIndex index,
- void* ElementPtr,
- ArrayIndex count)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TDynamicArray.ReplaceElementAt");
- }
- // The count computation for this blockmove makes sure that if the element size is not
- // a power of 2 that we don't copy more bytes back to the caller than required for a
- // given number of elements… sending the caller into orbit and heading straight for the Excedrin.
-
- // !!! NOTE MULTIPLE (> 1) element moves for non-power of 2 element sizes are not yet supported!
-
- if (count > kEmptyIndex)
- BlockMove(this->ComputeAddress(index), (Ptr)ElementPtr, ((count - 1) << fElementSizeShift) + fElementSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- // if qTrace Called _FREQUENTLY_
-
- pascal Ptr TDynamicArray::ComputeAddress(ArrayIndex index)
- {
- #if FALSE
- // This is the ideal situation. Unfortunately it is too slow for something as
- // widely used as Dynamic Arrays, so we break the encapsulation below. If your subclass
- // wishes to manage storage gotten from somewhere other than the object's handle then
- // you must override GetDynamicPtr to return a pointer to the storage to be managed and
- // ALSO override ComputeAddress to use this commented out code.
- Ptr p;
-
- p = this->GetDynamicPtr();
- if (qDebug && !p)
- DebugStr("ComputeAddress called with an empty list (no dynamic area allocated)");
-
- // p + ((index - 1) * fElementSize)
- return (Ptr)((long)p + (((index - 1)) << fElementSizeShift));
- #endif
-
- // Break encapsulation and just return an index off of this which we know to be a handle MacApp 2.0
- return (Ptr)(StripLong(*((Handle)this)) + fClassSize + ((index - 1) << fElementSizeShift));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::Free(void)
- {
- // She can't do it cap'n. The dilithium crystals are burrrrnt out! If they're
- // allowed to rest a while they might recover enough for another try.
- if (fIteratorPtr)
- {
- fFreeRequested = TRUE;
- // Release our dynamic portion now, but wait to be freed
- if (fSize > kEmptyIndex)
- this->DeleteElementsAt(1, fSize);
- }
- else
- inherited::Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal ArrayIndex TDynamicArray::GetSize(void)
- {
- return fSize;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::InsertElementsBefore(ArrayIndex index,
- void* ElementPtr,
- ArrayIndex count)
- {
- Ptr indexPtr, nextIndexPtr, lastElementPtr;
- ArrayIndex countBytes;
-
- if (qRangeCheck && ((index < 1) || (index > fSize + 1)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TDynamicArray.InsertBefore");
- }
-
- this->SetArraySize(fSize + count); // make sure there's room if needed
-
- indexPtr = this->ComputeAddress(index);
- nextIndexPtr = this->ComputeAddress(index + count);
- lastElementPtr = this->ComputeAddress(fSize + 1);
- countBytes = count << fElementSizeShift;
-
- if (index <= fSize) // clear out a hole?
- BlockMove(indexPtr, nextIndexPtr, (long)lastElementPtr - (long)indexPtr);
-
- // !!! we still don't account for multiple element moves with non power of 2 element sizes.
- // Would it be best to create a MoveElements method and put the smarts in it?
-
- if ((countBytes == sizeof(long)) &&!odd((Ptr)ElementPtr) &&!odd(indexPtr))
- *((long*)indexPtr) = *((long*)ElementPtr);// shortcut for longs
- else
- BlockMove((Ptr)ElementPtr, indexPtr, countBytes);// longcut for shorts (and other sizes)
-
- fSize += count;
-
- if (fIteratorPtr) // Keep all iterations apprised
- fIteratorPtr->InsertElementBefore(index, count);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal Boolean TDynamicArray::IsEmpty(void)
- {
- return (fSize == kEmptyIndex);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // DON'T use exit to get out of this routine from your TestElement function or you will be really
- // sad! (our debugger will check for you) That's why you can return TRUE to stop enumerating.
- // Signaling Failure is OK too.
- pascal ArrayIndex TDynamicArray::EachElementDoTil(TestIndexType TestElement,
- void* staticLink,
- Boolean IterateForward)
- {
- return this->EachElementInRangeDoTil(1, fSize, TestElement, staticLink, IterateForward);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // DON'T use exit to get out of this routine from your TestElement function or you will be really
- // sad! (our debugger will check for you) That's why you can return TRUE to stop enumerating.
- // Signaling Failure is OK too.
- pascal ArrayIndex TDynamicArray::EachElementInRangeDoTil(ArrayIndex lowBound,
- ArrayIndex highBound,
- TestIndexType TestElement,
- void* staticLink,
- Boolean IterateForward)
- {
- // Can't even special case one element lists, wouldn't be sure of index to return if the
- // TestElement call inserted or deleted.
- if (fSize > kEmptyIndex)
- {
- CArrayIterator iter(this, lowBound, highBound, IterateForward);
-
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- {
- if (TestElement(i, staticLink))
- return i;
- }
- }
- return kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::Merge(TDynamicArray* aDynamicArray)
- {
- if (qDebug && ((fElementSize != aDynamicArray->fElementSize) || (fElementSizeShift != aDynamicArray->fElementSizeShift)))
- ProgramBreak("In TDynamicArray->Merge: fElementSize or fElementSizeShift don't match with the TDynamicArray to merge!");
-
- if (aDynamicArray->GetSize() != kEmptyIndex)
- this->InsertElementsBefore(this->GetSize() + 1, aDynamicArray->ComputeAddress(1), aDynamicArray->GetSize());
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::ReplaceElementsAt(ArrayIndex index,
- void* ElementPtr,
- ArrayIndex count)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TDynamicArray.ReplaceElementAt");
- }
- BlockMove((Ptr)ElementPtr, this->ComputeAddress(index), count << fElementSizeShift);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TDynamicArray::SetArraySize(ArrayIndex theSize)
- {
- ArrayIndex newAllocatedSize;
-
- if ((theSize > fAllocatedSize) || (fAllocatedSize - theSize >= fAllocationIncrement))
- {
- if (qDebug && (fAllocationIncrement < 0))
- ProgramBreak("fAllocationIncrement < 0 ! You have serious problems.");
-
- // Set the # of allocated elements to the nearest multiple of fAllocationIncrement.
- // Wait until after the SetDynamicSize to set fAllocatedSize in case SetDynamicSize
- // signals failure.
- if (fAllocationIncrement)
- newAllocatedSize = (theSize + fAllocationIncrement) - (theSize + fAllocationIncrement) % fAllocationIncrement;
- else
- newAllocatedSize = theSize;
-
- if (newAllocatedSize != fAllocatedSize)
- this->SetDynamicSize(newAllocatedSize << fElementSizeShift);
-
- fAllocatedSize = newAllocatedSize;
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TDynamicArray::Fields(TObject* obj) // override
- {
- obj->DoToField("TDynamicArray", (Ptr)NULL, bClass);
- obj->DoToField("fIteratorPtr", (Ptr) & fIteratorPtr, bPointer);
- obj->DoToField("fSize", (Ptr) & fSize, bLongInt);
- obj->DoToField("fElementSize", (Ptr) & fElementSize, bInteger);
- obj->DoToField("fElementSizeShift", (Ptr) & fElementSizeShift, bInteger);
- obj->DoToField("fAllocationIncrement", (Ptr) & fAllocationIncrement, bLongInt);
- obj->DoToField("fAllocatedSize", (Ptr) & fAllocatedSize, bLongInt);
- obj->DoToField("fFreeRequested", (Ptr) & fFreeRequested, bBoolean);
- obj->DoToField("fClassSize", (Ptr) & fClassSize, bLongInt);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
- pascal void TDynamicArray::DynamicFields(TObject* obj)// override
- {
- obj->DoToField("Dynamic Fields", NULL, bTitle);
-
- CArrayIterator iter(this);
-
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- {
- Str255 aString;
-
- NumToString(i, aString);
- aString = ".At[" + aString + "]";
- obj->DoToField(aString, this->ComputeAddress(i), bPointer);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedDynamicArray::ISortedDynamicArray(ArrayIndex initialSize,
- short elementSize)
- {
- this->IDynamicArray(initialSize, elementSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal CompareResult TSortedDynamicArray::CompareElements(void* ,
- void*)
- {
- // By Default consider all items equal
- return kItem1EqualItem2;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // DON'T use exit to get out of this routine from your TestItem function or you will be really
- // sad! (our debugger will check for you) That's why you can return TRUE to stop enumerating.
- // Signaling Failure is OK too.
- pascal Boolean TSortedDynamicArray::DoSearchElement(CompareIndexType TestItem,
- void* staticLink,
- ArrayIndex& index)
- {
- Boolean found = FALSE;
-
- if (fSize == kEmptyIndex)
- index = 1;
- else
- {
- CompareResult aCompareResult;
- CArrayIterator iter(this);
-
- do
- {
- // (fLowBound + fHighBound) / 2
- iter.fCurrentIndex = (iter.fLowBound + iter.fHighBound) >> 1;
-
- aCompareResult = TestItem(iter.fCurrentIndex, staticLink);
-
- if (aCompareResult <= kItemGreaterThanCriteria)
- iter.fHighBound = iter.fCurrentIndex - 1;
- else
- iter.fLowBound = iter.fCurrentIndex + 1;
-
- } while (!((aCompareResult == kItemEqualCriteria) || (iter.fLowBound > iter.fHighBound)));
-
- if (aCompareResult == kItemEqualCriteria)
- found = TRUE;
- else if (aCompareResult >= kItemLessThanCriteria)
- ++iter.fCurrentIndex;
-
- // keep index in range
- if ((iter.fCurrentIndex < 1) || (iter.fCurrentIndex > fSize + 1))
- index = kEmptyIndex;
- else
- index = iter.fCurrentIndex;
-
- }
- return found;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CElementInserter
- {
- void*& fElementPtr;
- TSortedDynamicArray* fDynamicArray;
-
- public:
- CElementInserter(void*& theElementPtr,
- TSortedDynamicArray* theDynamicArray) :
- fElementPtr(theElementPtr),
- fDynamicArray(theDynamicArray)
- {
- }
-
- pascal CompareResult TestItem(ArrayIndex anItem);
-
- };
-
- #pragma segment ListRes
- pascal CompareResult CElementInserter::TestItem(ArrayIndex anItem)
- {
- return fDynamicArray->CompareElements(fElementPtr, fDynamicArray->ComputeAddress(anItem));
- }
-
- #pragma segment ListRes
- pascal void TSortedDynamicArray::InsertElementInOrder(void* elementPtr)
- {
- ArrayIndex index;
- CElementInserter anElementInserter(elementPtr, this);
-
- this->DoSearchElement((CompareIndexType) & CElementInserter::TestItem, &anElementInserter, index);
- this->InsertElementsBefore(index, elementPtr, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TSortedDynamicArray::Fields(TObject* obj)// override
- {
- obj->DoToField("TSortedDynamicArray", (Ptr)NULL, bClass);
-
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TList* NewList(void)
- {
- TList * list;
-
- list = new TList;
- list->IList();
- return list;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TSortedList* NewSortedList(void)
- {
- TSortedList * list;
-
-
- list = new TSortedList;
- list->ISortedList();
- return list;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TList* NewAllocatedList(ArrayIndex iSize)
- {
- TList * list;
-
- list = NewList();
- list->SetArraySize(iSize);
- return list;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TSortedList* FreeListIfObject(TSortedList* list)
- {
- if (list)
- {
- if (qDebug)
- FailNonObject(list);
-
- list->FreeList();
- }
- return (TSortedList *)NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::Initialize(void) // override
- {
- inherited::Initialize();
-
- fObjClassID = kNilClass;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Default comparison is identity
- pascal CompareResult TSortedList::Compare(TObject* item1,
- TObject* item2)
- {
- if (item1 > item2)
- return kItem1GreaterThanItem2;
- else if (item1 < item2)
- return kItem1LessThanItem2;
- else
- return kItem1EqualItem2;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal CompareResult TSortedList::CompareElements(void* element1,
- void* element2)// override
- {
- return this->Compare(*((TObjectPtrPtr)element1), *((TObjectPtrPtr)element2));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::ISortedList(void)
- {
- // Can't do sizeof(TObject) because sizeof
- // returns the record size for objects
- this->ISortedDynamicArray(kEmptyIndex, sizeof(Handle));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CSearchIndex
- {
- CompareObjectType& fTestItem;
- void*& fStaticLink;
- TObject*& fObject;
- TSortedList* fSortedList;
-
- public:
- // Constructor
- CSearchIndex(CompareObjectType& TestItem,
- void*& staticLink,
- TObject*& theObject,
- TSortedList* theSortedList) :
- fTestItem(TestItem),
- fStaticLink(staticLink),
- fObject(theObject),
- fSortedList(theSortedList)
- {
- }
-
- pascal CompareResult TestElement(ArrayIndex anItem);
- };
-
- #pragma segment ListRes
- pascal CompareResult CSearchIndex::TestElement(ArrayIndex anItem)
- {
- fObject = *((TObjectPtrPtr)fSortedList->ComputeAddress(anItem));// in case the index is deleted by the test.
- if (qDebug)
- FailNonObject(fObject);
- return fTestItem(fObject, fStaticLink);
- }
-
- #pragma segment ListRes
- // DON'T use exit to get out of this routine from your TestItem function or you will be really
- // sad! (our debugger will check for you).
- pascal TObject* TSortedList::DoSearch(CompareObjectType TestItem,
- void* staticLink,
- ArrayIndex& index)
- {
- TObject * obj;
- CSearchIndex aSearcher(TestItem, staticLink, obj, this);
-
- if (this->DoSearchElement((CompareIndexType) & CSearchIndex::TestElement, &aSearcher, index))
- return obj;
- else
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CObjectComparer
- {
- TObject*& fObject;
- TSortedList* fSortedList;
-
- public:
- // Constructor
- CObjectComparer(TObject*& theObject,
- TSortedList* theSortedList) :
- fObject(theObject),
- fSortedList(theSortedList)
- {
- }
-
- // if qTrace
- pascal CompareResult CompareObjects(TObject* anItem);
- };
-
- #pragma segment ListRes
- pascal CompareResult CObjectComparer::CompareObjects(TObject* anItem)
- {
- if (qDebug)
- FailNonObject(anItem);
- return fSortedList->Compare(fObject, anItem);
- }
-
- #pragma segment ListRes
- pascal ArrayIndex TSortedList::GetEqualItemNo(TObject* item)
- {
- ArrayIndex index;
- CObjectComparer anObjectComparer(item, this);
-
- if (qDebug)
- FailNonObject(item);
- if (this->DoSearch((CompareObjectType) & CObjectComparer::CompareObjects, &anObjectComparer, index))
- return index;
- else
- return kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::Insert(TObject* item)
- {
- if (qDebug)
- FailNonObject(item);
-
- this->InsertElementInOrder(&item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal void TSortedList::QuickSort(ArrayIndex beginIndex,
- ArrayIndex endIndex,
- CompareObjectsType CompareItems,
- void* staticLink)
- {
- TObject * pivot = NULL;
- TObject * firstKey;
- TObject * secondKey;
- ArrayIndex left = beginIndex;
- ArrayIndex right = endIndex;
-
- // Find the pivot value
- firstKey = this->At(beginIndex);
- for (ArrayIndex index = beginIndex + 1; index <= endIndex; ++index)// Scan for a different key
- {
- secondKey = this->At(index);
- short compareResults;
-
- if ((compareResults = CompareItems(secondKey, firstKey, staticLink)) >= kItem1GreaterThanItem2)
- {
- pivot = secondKey;
- break;
- }
- else if (compareResults <= kItem1LessThanItem2)
- {
- pivot = firstKey;
- break;
- }
- }
-
- if (pivot) // Don't do anything if the objects are all equal
- {
- do
- {
- TObject * leftObject = this->At(left);
- TObject * rightObject = this->At(right);
-
- // Swap the elements
- this->ReplaceElementsAt(left, &rightObject, 1);
- this->ReplaceElementsAt(right, &leftObject, 1);
-
- // now the scan phase begins
- while (CompareItems(this->At(left), pivot, staticLink) <= kItem1LessThanItem2)
- ++left;
- while (CompareItems(this->At(right), pivot, staticLink) >= kItem1EqualItem2)
- --right;
- } while (left <= right);
-
- this->QuickSort(beginIndex, left - 1, CompareItems, staticLink);
- this->QuickSort(left, endIndex, CompareItems, staticLink);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // if qTrace
- pascal CompareResult CompareObjects(TObject* item1,
- TObject* item2,
- void* staticLink)
- {
- return ((TSortedList *)staticLink)->Compare(item1, item2);
- }
-
-
- pascal void TSortedList::Sort(void)
- {
- this->QuickSort(1, fSize, CompareObjects, this);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- //!!! Sort would be nice to have at the TDynamicArray level too… Parameterized types where are you?
- // NOTE: This doesn't work with a CompareItems Function that inserts or deletes elements.
- pascal void TSortedList::SortBy(CompareObjectsType CompareItems,
- void* staticLink)
- {
- this->QuickSort(1, fSize, CompareItems, staticLink);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TSortedList::Search(CompareObjectType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->DoSearch(TestItem, staticLink, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TSortedList::Fields(TObject* obj) // override
- {
- MAName aString;
-
- obj->DoToField("TSortedList", (Ptr)NULL, bClass);
- GetClassNameFromID(fObjClassID, aString);
- obj->DoToField("fObjClassID", (Ptr) & aString, bString);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAInspector
-
- pascal void TSortedList::GetInspectorName(Str255& inspectorName)// override
- {
- if (fObjClassID != kNilClass)
- {
- GetClassNameFromID(fObjClassID, inspectorName);
- inspectorName = "Of " + inspectorName + " Size: ";
- ConcatNumber(inspectorName, this->GetSize(), inspectorName);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TSortedList::At(ArrayIndex index)
- {
- if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TList.At");
- }
-
- return *((TObjectPtrPtr)ComputeAddress(index));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::AtDelete(ArrayIndex index)
- {
- if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TList.AtDelete");
- }
-
- this->DeleteElementsAt(index, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::Delete(TObject* item)
- {
- ArrayIndex index;
-
- if (qDebug)
- FailNonObject(item);
- index = this->GetIdentityItemNo(item);
- if (index != kEmptyIndex)
- this->AtDelete(index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::DeleteAll(void)
- {
- if (fSize > kEmptyIndex)
- this->DeleteElementsAt(1, fSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal void TSortedList::Each(DoToObjectType DoToItem,
- void* staticLink)
- {
- CObjectIterator iter(this);
-
- for (TObject* obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
- DoToItem(obj, staticLink);
- }
-
-
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TSortedList::First(void)
- {
- if (fSize <= kEmptyIndex)
- return NULL;
- else
- return this->At(1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TSortedList::FirstThat(TestObjectType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->IterateTil(TestItem, staticLink, kIterateForward, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal void TSortedList::FreeAll(void)
- {
- CObjectIterator iter(this);
-
- for (TObject* obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
- FreeIfObject(obj);
-
- this->DeleteAll();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedList::FreeList(void)
- {
- this->FreeAll();
- this->Free();
- }
-
- //--------------------------------------------------------------------------------------------------
- // Search for the identity item. The list may ordered by some other
- // means than identity thus we must do a linear search to find the
- // requested item
- pascal ArrayIndex TSortedList::GetIdentityItemNo(TObject* item)
- {
- if (qDebug)
- FailNonObject(item);
-
- // the equality test should not change the list's size or the resulting index can be invalid
- CArrayIterator iter(this);
-
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- if (this->At(i) == item)
- return i;
- return kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
- pascal void TSortedList::DynamicFields(TObject* obj)// override
- {
- obj->DoToField("Dynamic Fields", (Ptr)NULL, bTitle);
-
- CArrayIterator iter(this);
-
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- {
- Str255 aString;
-
- NumToString(i, aString);
- aString = ".At[" + aString + "]";
- obj->DoToField(aString, this->ComputeAddress(i), bObject);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal TObject* TSortedList::IterateTil(TestObjectType TestItem,
- void* staticLink,
- Boolean IterateForward,
- ArrayIndex& itsIndex)
- {
- CArrayIterator iter(this, IterateForward);
-
- for (itsIndex = iter.FirstIndex(); iter.More(); itsIndex = iter.NextIndex())
- {
- TObject * testObject = this->At(itsIndex);
- if (TestItem(testObject, staticLink))
- return testObject;
- }
-
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TSortedList::Last(void)
- {
- if (fSize <= kEmptyIndex)
- return NULL;
- else
- return this->At(fSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TSortedList::LastThat(TestObjectType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->IterateTil(TestItem, staticLink, kIterateBackward, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListDebug
-
- pascal void TSortedList::SetEltType(const MAName& toClass)
- {
- MAName s;
-
- // Forgive the caller for calling this twice only if the same type was specified both times
- if (qDebug && (fObjClassID != kNilClass))
- {
- GetClassNameFromID(fObjClassID, s);
- if (toClass != s)
- {
- fprintf(stderr, "The list already contains %s; trying to change to %s\n",
- (char *) s, (char *) toClass);
- ProgramBreak("In TList.SetEltType");
- }
- }
- // Assign the field
- fObjClassID = GetClassIDFromName(toClass); // srf 88.9.7
- }
-
- //-------------------------------------------------------------------------------------------------
- #pragma segment ListDebug
-
- pascal void TSortedList::SetEltTypeID(ObjClassID toClassID)
- {
- MAName s, newClassName;
-
- // Forgive the caller for calling this twice only if the same type was specified both times
- if (qDebug && (fObjClassID != kNilClass))
- {
- if (fObjClassID != toClassID)
- {
- GetClassNameFromID(fObjClassID, s);
- GetClassNameFromID(toClassID, newClassName);
- fprintf(stderr, "The list already contains %s; trying to change to %s\n",
- (char *) s, (char *) newClassName);
- ProgramBreak("In TList.SetEltTypeID");
- }
- }
- // Assign the field
- fObjClassID = toClassID;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TList::IList(void)
- {
- this->ISortedList();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TList::AtPut(ArrayIndex index,
- TObject* newItem)
- {
- if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TList.AtPut");
- // Can't continue, bad index trashes memory ??? Would it be nice to
- // have a mechanism where the developer could supply a new index here?
- Failure(minErr, 0);
- }
-
- if (qDebug)
- {
- FailNonObject(newItem);
- if (fObjClassID != kNilClass)
- if (!IsMemberClassID(newItem, fObjClassID))
- {
- fprintf(stderr, "newItem: %p\n", newItem);
- ProgramBreak("In TList.AtPut: inserting invalid object type");
- }
- }
- *((TObjectPtrPtr)ComputeAddress(index)) = newItem;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- // DON'T use exit to get out of this routine from your TestItem function or you will be really
- // sad! (our debugger will check for you) That's why you can return TRUE to stop enumerating.
- // Signaling Failure is OK too.
- pascal Boolean TList::DoSearchElement(CompareIndexType TestItem,
- void* staticLink,
- ArrayIndex& index)// override
- {
- CArrayIterator iter(this);
-
- for (index = iter.FirstIndex(); iter.More(); index = iter.NextIndex())
- if (TestItem(index, staticLink) == kItem1EqualItem2)
- return TRUE;
-
- index = fSize + 1;
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Overridden to do arrival sequence insertion
- pascal void TList::InsertElementInOrder(void* ElementPtr)// override
- {
- this->InsertElementsBefore(fSize + 1, ElementPtr, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TList::InsertBefore(ArrayIndex index,
- TObject* item)
- {
- if (qRangeCheck && ((index <= kEmptyIndex) || (index > fSize + 1)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TList.InsertBefore");
- }
-
- if (qDebug)
- {
- FailNonObject(item);
- if (fObjClassID != kNilClass)
- if (!IsMemberClassID(item, fObjClassID))
- {
- fprintf(stderr, "item: %p\n", item);
- ProgramBreak("In TList.InsertBefore: inserting invalid object type");
- }
- }
- this->InsertElementsBefore(index, &item, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TList::InsertFirst(TObject* item)
- {
- // Depend on InsertBefore for sanity checking
- this->InsertBefore(1, item);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- pascal void TList::InsertLast(TObject* item)
- {
- // Depend on InsertBefore for sanity checking
- this->InsertBefore(fSize + 1, item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TList::Fields(TObject* obj) // override
-
- {
- obj->DoToField("TList", (Ptr)NULL, bClass);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TList::Push(TObject* item)
- {
- // Depend on InsertBefore for sanity checking
- this->InsertLast(item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TList::Pop(void)
- {
- TObject * topOfStack;
-
- if (fSize == kEmptyIndex)
- topOfStack = NULL;
- else
- {
- topOfStack = this->At(fSize);
- this->AtDelete(fSize);
- }
- return topOfStack;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TList::Queue(TObject* item)
- {
- // Depend on InsertBefore for sanity checking
- this->InsertLast(item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal TObject* TList::Dequeue(void)
- {
- TObject * beginningOfStack;
-
- if (fSize <= kEmptyIndex)
- beginningOfStack = NULL;
- else
- {
- beginningOfStack = this->At(1);
- this->AtDelete(1);
- }
- return beginningOfStack;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void THandleList::IHandleList(void)
- {
- // Initialize a new list with no elements, i.e., fSize == 0
- this->ISortedDynamicArray(kEmptyIndex, sizeof(Handle));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Return the index'th element of the list.
- pascal Handle THandleList::At(ArrayIndex index)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in THandleList.At");
- }
-
- return *((HandlePtr)ComputeAddress(index));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Deletes via an index.
- pascal void THandleList::AtDelete(ArrayIndex index)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in THandleList.AtDelete");
- }
- this->DeleteElementsAt(index, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void THandleList::Delete(Handle item)
- {
- ArrayIndex index;
-
- index = this->GetIdentityItemNo(item);
- if (index != kEmptyIndex)
- this->AtDelete(index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void THandleList::DeleteAll(void)
- {
- if (fSize > kEmptyIndex)
- this->DeleteElementsAt(1, fSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CSearchHandleIndex
- {
- CompareHandleType& fTestItem;
- void*& fStaticLink;
- Handle& fHandle;
- THandleList* fHandleList;
-
- public:
- // Constructor
- CSearchHandleIndex(CompareHandleType& TestItem,
- void*& staticLink,
- Handle& theHandle,
- THandleList* theHandleList) :
- fTestItem(TestItem),
- fStaticLink(staticLink),
- fHandle(theHandle),
- fHandleList(theHandleList)
- {
- }
-
- pascal CompareResult TestElement(ArrayIndex anItem);
- };
-
- #pragma segment ListRes
- pascal CompareResult CSearchHandleIndex::TestElement(ArrayIndex anItem)
- {
- fHandle = fHandleList->At(anItem);
- return fTestItem(fHandle, fStaticLink);
- }
-
- #pragma segment ListRes
- // DON'T use exit to get out of this routine from your TestItem function or you will be really
- // sad! (our debugger will check for you).
- pascal Handle THandleList::DoSearch(CompareHandleType TestItem,
- void* staticLink,
- ArrayIndex& index)
- {
- Handle aHandle = NULL;
- CSearchHandleIndex aSearcher(TestItem, staticLink, aHandle, this);
-
- if (this->DoSearchElement((CompareIndexType) & CSearchHandleIndex::TestElement, &aSearcher, index))
- return aHandle;
- else
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal void THandleList::Each(DoToHandleType DoToItem,
- void* staticLink)
- {
- CHandleIterator iter(this);
-
- for (Handle aHandle = iter.FirstHandle(); iter.More(); aHandle = iter.NextHandle())
- DoToItem(aHandle, staticLink);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Return the first element of the list.
- pascal Handle THandleList::First(void)
- {
- if (fSize <= kEmptyIndex)
- return NULL;
- else
- return this->At(1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Call DoToItem once for each element of the list, in order.
- pascal Handle THandleList::FirstThat(TestHandleType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->IterateTil(TestItem, staticLink, kIterateForward, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal Boolean EqualHandles(Handle listItem,
- void* staticLink)
- {
- if (listItem == (Handle)staticLink)
- return TRUE;
- else
- return FALSE;
- }
-
- // Find the first reference to the IDENTITY item in the list.
- // If item does not occur, return 0.
- pascal ArrayIndex THandleList::GetIdentityItemNo(Handle item)
- {
- ArrayIndex index;
-
- this->IterateTil(EqualHandles, item, kIterateForward, index);
- return index;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CHandleComparer
- {
- Handle& fHandle;
- THandleList* fHandleList;
-
- public:
- // Constructor
- CHandleComparer(Handle& theHandle,
- THandleList* theHandleList) :
- fHandle(theHandle),
- fHandleList(theHandleList)
- {
- }
-
- // if qTrace
- pascal CompareResult CompareHandles(Handle anItem);
- };
-
- #pragma segment ListRes
- pascal CompareResult CHandleComparer::CompareHandles(Handle anItem)
- {
- return fHandleList->Compare(fHandle, anItem);
- }
-
- #pragma segment ListRes
- // Find the first reference to item in the list.
- // If item does not occur, return 0.
- pascal ArrayIndex THandleList::GetEqualItemNo(Handle item)
- {
- ArrayIndex index;
- CHandleComparer aHandleComparer(item, this);
-
- if (this->DoSearch((CompareHandleType) & CHandleComparer::CompareHandles, &aHandleComparer, index))
- return index;
- else
- return kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void THandleList::Insert(Handle item)
- {
- this->InsertElementInOrder(&item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // By default just compare the ordinal value of the items. Subclasses that want to use the items
- // as pointers or other types should override if the comparison is based on the pointed at value
- pascal CompareResult THandleList::Compare(Handle item1,
- Handle item2)
- {
- if (item1 > item2)
- return kItem1GreaterThanItem2;
- else if (item1 < item2)
- return kItem1LessThanItem2;
- else
- return kItem1EqualItem2;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal CompareResult THandleList::CompareElements(void* element1,
- void* element2)// override
- {
- return this->Compare(*((HandlePtr)element1), *((HandlePtr)element2));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal Handle THandleList::IterateTil(TestHandleType TestItem,
- void* staticLink,
- Boolean IterateForward,
- ArrayIndex& itsIndex)
- {
- CArrayIterator iter(this, IterateForward);
-
- for (itsIndex = iter.FirstIndex(); iter.More(); itsIndex = iter.NextIndex())
- {
- Handle testHandle = this->At(itsIndex);
- if (TestItem(testHandle, staticLink))
- return testHandle;
- }
-
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Return the last element of the list.
- pascal Handle THandleList::Last(void)
- {
- if (fSize <= kEmptyIndex)
- return NULL;
- else
- return this->At(fSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Call DoToItem once for each element of the list, in order.
- pascal Handle THandleList::LastThat(TestHandleType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->IterateTil(TestItem, staticLink, kIterateBackward, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void THandleList::Fields(TObject* obj) // override
- {
- obj->DoToField("THandleList", (Ptr)NULL, bClass);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
- pascal void THandleList::DynamicFields(TObject* obj)// override
- {
- obj->DoToField("Dynamic Fields", (Ptr)NULL, bTitle);
-
- CArrayIterator iter(this);
-
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- {
- Str255 aString;
-
- NumToString(i, aString);
- aString = ".At[" + aString + "]";
- obj->DoToField(aString, this->ComputeAddress(i), bHandle);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedLongintList::ISortedLongintList(void)
- {
- // Initialize a new list with no elements, i.e., fSize == 0
- this->ISortedDynamicArray(kEmptyIndex, sizeof(long));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Return the index'th element of the list.
- pascal long TSortedLongintList::At(ArrayIndex index)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TSortedLongintList.At");
- }
-
- return *((LongIntPtr)ComputeAddress(index));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Deletes via an index.
- pascal void TSortedLongintList::AtDelete(ArrayIndex index)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TSortedLongintList.AtDelete");
- }
-
- this->DeleteElementsAt(index, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedLongintList::Delete(long item)
- {
- ArrayIndex index;
-
- index = this->GetIdentityItemNo(item);
- if (index != kEmptyIndex)
- this->AtDelete(index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedLongintList::DeleteAll(void)
- {
- if (fSize > kEmptyIndex)
- this->DeleteElementsAt(1, fSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal void TSortedLongintList::Each(DoToLongType DoToItem,
- void* staticLink)
- {
- CLongintIterator iter(this);
-
- for (long aLong = iter.FirstLong(); iter.More(); aLong = iter.NextLong())
- DoToItem(aLong, staticLink);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Return the first element of the list.
- pascal long TSortedLongintList::First(void)
- {
- if (fSize <= kEmptyIndex)
- return 0;
- else
- return this->At(1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Call DoToItem once for each element of the list, in order.
- pascal long TSortedLongintList::FirstThat(TestLongType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->IterateTil(TestItem, staticLink, kIterateForward, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal Boolean TestItem(long listItem,
- void* staticLink)
- {
- if (listItem == *((LongIntPtr)staticLink))
- return TRUE;
- else
- return FALSE;
- }
-
- // Find the first reference to the IDENTITY item in the list.
- // If item does not occur, return 0.
- pascal ArrayIndex TSortedLongintList::GetIdentityItemNo(long item)
- {
- ArrayIndex index;
-
- this->IterateTil(TestItem, &item, kIterateForward, index);
- return index;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
- pascal long TSortedLongintList::IterateTil(TestLongType TestItem,
- void* staticLink,
- Boolean IterateForward,
- ArrayIndex& itsIndex)
- {
- CArrayIterator iter(this, IterateForward);
-
- for (itsIndex = iter.FirstIndex(); iter.More(); itsIndex = iter.NextIndex())
- {
- long testLong = this->At(itsIndex);
- if (TestItem(testLong, staticLink))
- return testLong;
- }
-
- return 0;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Return the last element of the list.
- pascal long TSortedLongintList::Last(void)
- {
- if (fSize <= kEmptyIndex)
- return 0;
- else
- return this->At(fSize);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Call DoToItem once for each element of the list, in order.
- pascal long TSortedLongintList::LastThat(TestLongType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->IterateTil(TestItem, staticLink, kIterateBackward, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // By default just compare the ordinal value of the items. Subclasses that want to use the items
- // as pointers or other types should override if the comparison is based on the pointed at value
- pascal CompareResult TSortedLongintList::Compare(long item1,
- long item2)
- {
- if (item1 > item2)
- return kItem1GreaterThanItem2;
- else if (item1 < item2)
- return kItem1LessThanItem2;
- else
- return kItem1EqualItem2;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal CompareResult TSortedLongintList::CompareElements(void* element1,
- void* element2)// override
- {
- return this->Compare(*((LongIntPtr)element1), *((LongIntPtr)element2));
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CSearchLongIndex
- {
- CompareLongType& fTestItem;
- void*& fStaticLink;
- long& fLong;
- TSortedLongintList* fLongintList;
-
- public:
- // Constructor
- CSearchLongIndex(CompareLongType& TestItem,
- void*& staticLink,
- long& theLong,
- TSortedLongintList* theLongintList) :
- fTestItem(TestItem),
- fStaticLink(staticLink),
- fLong(theLong),
- fLongintList(theLongintList)
- {
- }
-
- pascal CompareResult TestElement(ArrayIndex anItem);
- };
-
- #pragma segment ListRes
- pascal CompareResult CSearchLongIndex::TestElement(ArrayIndex anItem)
- {
- fLong = fLongintList->At(anItem);
- return fTestItem(fLong, fStaticLink);
- }
-
- #pragma segment ListRes
- // DON'T use exit to get out of this routine from your TestItem function or you will be really
- // sad! (our debugger will check for you).
- pascal long TSortedLongintList::DoSearch(CompareLongType TestItem,
- void* staticLink,
- ArrayIndex& index)
- {
- long aLong = NULL;
- CSearchLongIndex aSearcher(TestItem, staticLink, aLong, this);
-
- if (this->DoSearchElement((CompareIndexType) & CSearchLongIndex::TestElement, &aSearcher, index))
- return aLong;
- else
- return NULL;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- class CLongComparer
- {
- long& fLong;
- TSortedLongintList* fSortedLongintList;
-
- public:
- // Constructor
- CLongComparer(long& theLong,
- TSortedLongintList* theSortedLongintList) :
- fLong(theLong),
- fSortedLongintList(theSortedLongintList)
- {
- }
-
- // if qTrace
- pascal CompareResult CompareLongs(long anItem);
- };
-
- #pragma segment ListRes
- pascal CompareResult CLongComparer::CompareLongs(long anItem)
- {
- return fSortedLongintList->Compare(fLong, anItem);
- }
-
- #pragma segment ListRes
- // Find the first reference to item in the list.
- // If item does not occur, return 0.
- pascal ArrayIndex TSortedLongintList::GetEqualItemNo(long item)
- {
- ArrayIndex index;
- CLongComparer aLongComparer(item, this);
-
- if (this->DoSearch((CompareLongType) & CLongComparer::CompareLongs, &aLongComparer, index))
- return index;
- else
- return kEmptyIndex;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TSortedLongintList::Insert(long item)
- {
- this->InsertElementInOrder(&item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal long TSortedLongintList::Search(CompareLongType TestItem,
- void* staticLink)
- {
- ArrayIndex index;
-
- return this->DoSearch(TestItem, staticLink, index);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TSortedLongintList::Fields(TObject* obj)// override
- {
- obj->DoToField("TSortedLongintList", (Ptr)NULL, bClass);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
- pascal void TSortedLongintList::DynamicFields(TObject* obj)// override
- {
- obj->DoToField("Dynamic Fields", (Ptr)NULL, bTitle);
-
- CArrayIterator iter(this);
-
- for (ArrayIndex i = iter.FirstIndex(); iter.More(); i = iter.NextIndex())
- {
- Str255 aString;
-
- NumToString(i, aString);
- aString = ".At[" + aString + "]";
- obj->DoToField(aString, this->ComputeAddress(i), bLongInt);
- }
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- pascal void TLongintList::ILongintList(void)
- {
- // Initialize a new list with no elements, i.e., fSize == 0
- this->ISortedLongintList();
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // DON'T use exit to get out of this routine from your TestItem function or you will be really
- // sad! (our debugger will check for you) That's why you can return TRUE to stop enumerating.
- // Signaling Failure is OK too.
- pascal Boolean TLongintList::DoSearchElement(CompareIndexType TestItem,
- void* staticLink,
- ArrayIndex& index)// override
- {
- CArrayIterator iter(this);
-
- for (index = iter.FirstIndex(); iter.More(); index = iter.NextIndex())
- if (TestItem(index, staticLink) == kItem1EqualItem2)
- return TRUE;
-
- index = fSize + 1;
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Overridden to do arrival sequence insertion
- pascal void TLongintList::InsertElementInOrder(void* ElementPtr)// override
- {
- this->InsertElementsBefore(fSize + 1, ElementPtr, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Replace the index'th element of the list.
- // Range check only if the compile-flag qRangeCheck is TRUE.
- pascal void TLongintList::AtPut(ArrayIndex index,
- long newItem)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TLongintList.AtPut");
- }
-
- *((LongIntPtr)ComputeAddress(index)) = newItem;
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Insert a reference to item at the indicated index.
- pascal void TLongintList::InsertBefore(ArrayIndex index,
- long item)
- {
- if (qRangeCheck && ((index < 1) || (index > fSize + 1)))
- {
- fprintf(stderr, "fSize == %1d index == %1d\n", fSize, index);
- ProgramBreak("Range Check in TLongintList.InsertBefore");
- }
-
- this->InsertElementsBefore(index, &item, 1);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // Insert a reference to item at the front of the list.
- pascal void TLongintList::InsertFirst(long item)
- {
- this->InsertBefore(1, item);
- }
-
- //--------------------------------------------------------------------------------------------------
-
- // Insert a reference to item at the back of the list.
- pascal void TLongintList::InsertLast(long item)
- {
- this->InsertBefore(fSize + 1, item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment MAFields
-
- pascal void TLongintList::Fields(TObject* obj) // override
- {
- obj->DoToField("TLongintList", (Ptr)NULL, bClass);
- inherited::Fields(obj);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // LIFO stack push.
- pascal void TLongintList::Push(long item)
- {
- this->InsertLast(item);
- }
-
- //--------------------------------------------------------------------------------------------------
- #pragma segment ListRes
-
- // LIFO stack pop
- pascal long TLongintList::Pop(void)
- {
- long topOfStack;
-
- if (fSize == kEmptyIndex)
- topOfStack = 0;
- else
- {
- topOfStack = this->At(fSize);
- this->AtDelete(fSize);
- }
- return topOfStack;
- }
-
-
-